home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <limits.h>
- #include "dnsconf.h"
- #include "internal.h"
- #include "../netconf/netconf.h"
- #include "dnsconf.m"
-
- static DNSCONF_HELP_FILE help_primary("primary");
-
- /*
- Used to read back an existing configuration
- */
- PUBLIC PRIMARY::PRIMARY(
- const char *_domain,
- const char *_file, // File used to store the configuration
- const char *named_dir) // Default directory for configuration files
- {
- domain.setfrom (_domain);
- file.setfrom (_file);
- origins.read (named_dir,_file,_domain);
- domainv.setfrom (_domain);
- isrev = 0;
- }
-
- PUBLIC PRIMARY::PRIMARY()
- {
- isrev = 0;
- }
- /*
- Update the domain name from the visual one.
- */
- PUBLIC VIRTUAL void PRIMARY::setfromv()
- {
- domain.setfrom (domainv);
- }
-
- /*
- Used to read back an existing configuration
- */
- PUBLIC PRIMARY_REV::PRIMARY_REV(
- const char *_domain,
- const char *_file, // File used to store the configuration
- const char *named_dir) // Default directory for configuration files
- : PRIMARY(_domain,_file,named_dir)
- {
- IP_ADDR ipa;
- ipa.setfrom (_domain);
- ipa.reverse ();
- ipa.shift();
- domainv.setfrom (ipa.get());
- isrev = 1;
- }
-
- PUBLIC PRIMARY_REV::PRIMARY_REV()
- {
- }
-
- /*
- Update the domain name from the visual one.
- */
- PUBLIC void PRIMARY_REV::setfromv()
- {
- IP_ADDR ipa;
- ipa.setfrom (domainv.get());
- char buf[30];
- ipa.setrev (buf);
- domain.setfrom (buf);
- }
-
- /*
- Return != if any component of the PRIMARY was modified
- */
- PUBLIC int PRIMARY::was_modified()
- {
- int ret = ARRAY_OBJ::was_modified();
- if (!ret){
- ret = origins.was_modified();
- }
- return ret;
- }
-
- /*
- Return != 0 if the PRIMARY describe the reverse mapping of an
- IP network (x.y,z.in-addr.arpa)
- */
- PUBLIC VIRTUAL int PRIMARY::is_reverse()
- {
- return 0;
- }
- /*
- Return != 0 if the PRIMARY describe the reverse mapping of an
- IP network (x.y,z.in-addr.arpa)
- */
- PUBLIC int PRIMARY_REV::is_reverse()
- {
- return 1;
- }
-
- /*
- Locate all IP number in use in a domain.
- Return the number added to adrs
- */
- PUBLIC int PRIMARY::getalladr(IP_ADDRS &adrs)
- {
- int ret = 0;
- for (int i=0; i<origins.getnb(); i++){
- ret += origins.getitem(i)->getalladr(adrs);
- }
- return ret;
- }
-
- /*
- Find the first record of a certain type in the PRIMARY
- Returne NULL if not found.
- */
- PRIVATE RECORD *PRIMARY::getfirst(RECORD_TYPE rtype)
- {
- RECORD *ret = NULL;
- for (int i=0; ret == NULL && i<origins.getnb(); i++){
- ORIGIN *ori = origins.getitem(i);
- for (int o=0; o<ori->tbrec.getnb(); o++){
- RECORD *rec = ori->tbrec.getitem(o);
- if (rec->is(rtype)){
- ret = rec;
- break;
- }
- }
- }
- return ret;
- }
- /*
- Find the (first) soa record of a primary
- Return NULL if it can be found.
- */
- PROTECTED RECORD_IN_SOA *PRIMARY::getsoa()
- {
- return (RECORD_IN_SOA*)getfirst(RTYPE_SOA);
- }
- /*
- Find all the NS records for a name.
- Return the number of record found.
- */
- PUBLIC int PRIMARY::getns(
- SSTRING &dom,
- RECORDS &recs)
- {
- FQHOST fq (dom);
- return locate_left (fq,RTYPE_NS,recs);
- }
- /*
- Find all the NS records for a name.
- Return the number of record found.
- */
- PUBLIC int PRIMARY::getns(
- SSTRING &dom,
- SSTRINGS &strs)
- {
- RECORDS recs;
- int nb = getns (dom,recs);
- for (int i=0; i<nb; i++){
- RECORD_IN_NS *ns = (RECORD_IN_NS*)recs.getitem(i);
- strs.add (new SSTRING (ns->ns));
- }
- return nb;
- }
- /*
- Find all the MX records for name.
- Return the number of record found.
- */
- PUBLIC int PRIMARY::getmx(
- SSTRING &dom,
- RECORDS &recs)
- {
- FQHOST fq (dom);
- return locate_left (fq,RTYPE_MX,recs);
- }
- /*
- Find all the MX records for a name.
- Return the number of record found.
- */
- PUBLIC int PRIMARY::getmx(
- SSTRING &dom,
- SSTRINGS &strs)
- {
- RECORDS recs;
- int nb = getmx (dom,recs);
- for (int i=0; i<nb; i++){
- RECORD_IN_MX *mx = (RECORD_IN_MX*)recs.getitem(i);
- strs.add (new SSTRING (mx->servname));
- }
- return nb;
- }
- /*
- Find all the A records for a name.
- Return the number of record found.
- */
- PUBLIC int PRIMARY::geta(
- SSTRING &dom,
- RECORDS &recs)
- {
- FQHOST fq (dom);
- return locate_left (fq,RTYPE_A,recs);
- }
-
- /*
- Find all the A records for a name.
- Return the number of record found.
- */
- PUBLIC int PRIMARY::geta(
- SSTRING &dom,
- IP_ADDRS &adrs)
- {
- RECORDS recs;
- int nb = geta (dom,recs);
- for (int i=0; i<nb; i++){
- RECORD_IN_A *a = (RECORD_IN_A*)recs.getitem(i);
- adrs.add (new IP_ADDR (a->addr));
- }
- return nb;
- }
- /*
- Find the CNAME record for a name.
- Return -1 if not found. cname will be empty.
- */
- PUBLIC int PRIMARY::getcname(
- SSTRING &dom,
- SSTRING &cname)
- {
- FQHOST fq (dom);
- RECORDS recs;
- int nb = locate_left (fq,RTYPE_CNAME,recs);
- cname.setfrom ("");
- int ret = -1;
- if (nb > 0){
- RECORD_IN_CNAME *a = (RECORD_IN_CNAME*)recs.getitem(0);
- cname.setfrom (a->name);
- ret = 0;
- }
- return ret;
- }
-
- /*
- Increment if needed the serial number of the SOA
- This function may be called several time. The serial number
- will be incremented only once per session though.
- */
- PUBLIC void PRIMARY::updatesoa()
- {
- if (origins.was_modified()){
- RECORD_IN_SOA *soa = getsoa();
- if (soa != NULL) soa->update(domain.get());
- }
- }
- /*
- Write the records of the domain and the entry in named.boot
- Return -1 if any error.
- */
- PUBLIC int PRIMARY::write (FILE *fout, const char *named_dir) const
- {
- int ret = origins.save (named_dir,file.get());
- fprintf (fout,"primary\t%s\t%s\n",domain.get(),file.get());
- return ret;
- }
-
-
- /*
- Add a record in the PRIMARY.
- The record is record relative to the main origin of the primary.
- */
- PUBLIC void PRIMARY::addrec (RECORD *rec)
- {
- if (origins.getnb()==0){
- ORIGIN *ori = new ORIGIN(domain.get());
- origins.add (ori);
- }
- origins.getitem(0)->tbrec.add (rec);
- }
-
-
- /*
- Edit the basic specs of a domain.
- Return -1 if the user abort edition
- Return 0 if the user accepted the changes
- Return 1 if the user wish to delete this domain.
- */
- PUBLIC int PRIMARY::edit(DNS &dns)
- {
- THISHOST thost;
- DIALOG dia;
- dia.newf_str (isrev ? MSG_U(F_NETNUM,"Network number")
- : MSG_U(F_DOMAIN,"Domain"),domainv);
- RECORD_IN_SOA *soa = getsoa();
- SSTRINGS rns;
- if (getns(domain,rns) == 0){
- rns.add (new SSTRING (thost.getname1()));
- }
- /* #Specification: dnsconf / main ns records of the domain
- dnsconf allows the specification of up to 3 NS
- record for a primary.
- */
- while (rns.getnb() < 3) rns.add (new SSTRING);
- SSTRINGS rmx;
- if (getmx(domain,rmx) == 0){
- rmx.add (new SSTRING (thost.getname1()));
- }
- /* #Specification: dnsconf / main mx records of the domain
- dnsconf allows the specification of up to 3 MX
- records for a primary.
- */
- while (rmx.getnb() < 3) rmx.add (new SSTRING);
- if (soa == NULL) soa = new RECORD_IN_SOA;
- dia.newf_str (MSG_U(F_MAINSERV,"Main server"),soa->machine);
- dia.newf_str (MSG_U(F_ADMINMAIL,"Administrator email"),soa->admin);
-
- dia.newf_title ("",MSG_R(F_DNSADV));
- int i;
- for (i=0; i<rns.getnb(); i++){
- dia.newf_str ("",*(rns.getitem(i)));
- }
-
- dia.newf_title ("",MSG_R(F_EMAILADV));
- for (i=0; i<rmx.getnb(); i++){
- dia.newf_str ("",*(rmx.getitem(i)));
- }
- dia.newf_title ("",MSG_U(F_SECREQ,"Secondaries requirements"));
- dia.newf_str (MSG_U(F_REFRESH,"Refresh"),soa->refresh);
- dia.newf_str (MSG_U(F_RETRY,"Retry"),soa->retry);
- dia.newf_str (MSG_U(F_EXPIRE,"Expire"),soa->expire);
- dia.newf_title ("",MSG_U(F_EVERYHOSTS,"Every hosts requirements"));
- dia.newf_str (MSG_U(F_TTL,"Time to live"),soa->default_ttl);
- int ret = -1;
- int nof = 0;
- while (1){
- MENU_STATUS status = dia.edit (
- MSG_U(T_PRIMSPEC,"Primary specification")
- ,MSG_U(I_PRIMSPEC,"You must enter a domain name\n")
- ,help_primary.getpath()
- ,nof
- ,MENUBUT_CANCEL|MENUBUT_ACCEPT|MENUBUT_DEL);
- if (status == MENU_CANCEL || status == MENU_ESCAPE){
- break;
- }else if (status == MENU_DEL){
- if (xconf_areyousure(MSG_U(Q_DELPRIMARY
- ,"Confirm deletion of a domain"))){
- ret = 1;
- break;
- }
- }else{
- if (domainv.is_empty()){
- xconf_error(MSG_U(E_NODOMAIN,"Fill at least the domain\n"
- "and the first IP address"));
- }else{
- setfromv();
- if (getsoa()==NULL) addrec (soa);
- /* #Specification: dnsconf / primary / record file
- dnsconf use the domain name as the file name
- which will contain the record.
-
- You can change the name in /etc/named.boot and dnsconf
- will use this one instead.
- */
- if (file.is_empty) file.setfrom (domainv);
- dns.setmx (domain,rmx);
- dns.setns (domain,rns);
- setmodified();
- ret = 0;
- break;
- }
- }
- }
- if (ret != 0) dia.restore();
- return ret;
- }
-
-
-
- PUBLIC PRIMARY *PRIMARYS::getitem (int no) const
- {
- return (PRIMARY*)ARRAY::getitem(no);
- }
-
- /*
- Locate all IP number in use in all domain of this DNS.
- Return the number added to adrs
- */
- PUBLIC int PRIMARYS::getalladr(IP_ADDRS &adrs)
- {
- int ret = 0;
- for (int i=0; i<getnb(); i++){
- ret += getitem(i)->getalladr(adrs);
- }
- return ret;
- }
- /*
- Get a PRIMARY for a fully qualified host.
- Get the primary that is the closest to the hostname
- (ie: x.y.z.com will select y.z.com instead of z.com if both
- domain are defined in this DNS).
- Return NULL if not found.
- */
- PUBLIC PRIMARY *PRIMARYS::getitem(
- FQHOST &fq,
- char *hostpart,
- int dontitself) // if dontitself != 0
- // && fq is itself a domain
- // don't select it
- {
- /* #Specification: dnsconf / matching a primary / closest
- When trying to dispatch information about a host
- in the DNS, dnsconf try to find the primary which
- has the closest match. This means that if a DNS
- is a primary for x.y.com and y.com, and dnsconf
- dispatch info about the host host.x.y.com, it will
- select the domain x.y.com.
-
- On the other end, host.w.y.com will be dispatch
- in the domain y.com.
- */
- PRIMARY *ret = NULL;
- int minlevel = 100;
- if (hostpart != NULL) hostpart[0] = '\0';
- for (int i=0; i<getnb(); i++){
- PRIMARY *pri = getitem(i);
- char tmp[200];
- int level = fq.is_member(pri->domain.get(),tmp);
- if (level > 0 && level < minlevel){
- if (!dontitself || strcmp(tmp,"@")!=0){
- ret = pri;
- minlevel = level;
- if (hostpart != NULL) strcpy (hostpart,tmp);
- }
- }
- }
- return ret;
- }
-
- /*
- Get a PRIMARY for a fully qualified host.
- Get the primary that is the closest to the hostname
- (ie: x.y.z.com will select y.z.com instead of z.com if both
- domain are defined in this DNS).
- Return NULL if not found.
- */
- PUBLIC PRIMARY *PRIMARYS::getitem(FQHOST &fq, char *hostpart)
- {
- return getitem (fq,hostpart,0);
- }
-
-
- PUBLIC int PRIMARYS::write (FILE *fout, const char *named_dir) const
- {
- int ret = 0;
- for (int i=0; i<getnb(); i++){
- if (getitem(i)->write(fout,named_dir) == -1) ret = -1;
- }
- return ret;
- }
-
- PUBLIC VIRTUAL PRIMARY *PRIMARYS::new_PRIMARY()
- {
- return new PRIMARY;
- }
- PUBLIC PRIMARY *PRIMARYS_REV::new_PRIMARY()
- {
- return new PRIMARY_REV;
- }
-
- static int cmp_by_name (const ARRAY_OBJ *o1, const ARRAY_OBJ *o2)
- {
- PRIMARY *s1 = (PRIMARY*)o1;
- PRIMARY *s2 = (PRIMARY*)o2;
- return s1->domainv.cmp(s2->domainv);
- }
-
-
- /*
- Present the list of primarys. Show selectivly the
- standard domain primaris or the reverse mapping primarys.
- */
- PUBLIC void PRIMARYS::edit(DNS &dns)
- {
- int choice=0;
- while (1){
- int nb = getnb();
- /* #Specification: domains / edition / sorting
- Domain are always sorted before being presented. This changes
- the ordering in /etc/named.boot.
- */
- sort(cmp_by_name);
- DIALOG dia;
- for (int i=0; i<nb; i++){
- PRIMARY *pri = getitem(i);
- dia.new_menuitem (" ",pri->domainv);
- }
- dia.addwhat (MSG_U(I_ADDPRIM,"add one primary spec"));
- MENU_STATUS code = dia.editmenu(
- MSG_U(T_PRIMARYS,"Primarys")
- ,MSG_U(I_PRIMARYS
- ,"You are allowed to edit/add/remove primaries\n")
- ,help_primary
- ,choice,0);
- if (code == MENU_QUIT || code == MENU_ESCAPE){
- break;
- }else if (code == MENU_ADD){
- PRIMARY *pri = new_PRIMARY();
- add (pri);
- if (pri->edit(dns) != 0){
- remove_del (pri);
- }else{
- /* #Specification: dnsconf / new primary / host info
- Whenever we add a new primary, we
- try to update the basic host information
- of this host so the DNS will be
- automaticly current.
- */
- netconf_updatedns();
- dns.write();
- }
- }else if (choice >= 0 && choice < nb){
- PRIMARY *pri = getitem(choice);
- int ok = pri->edit(dns);
- if (ok >= 0){
- if (ok == 1) remove_del(pri);
- dns.write();
- }
- }
- }
-
- }
-